class IUP_DIAL
-- Creates a dial for regulating a given angular variable. It inherits from 
-- IUP_CANVAS.
--
-- Notes:
--
-- When the keyboard arrows are pressed and released the mouse press and the 
-- mouse release callbacks are called in this order. If you hold the key down 
-- the mouse move callback is also called for every repetition.
--
-- When the wheel is rotated only the mouse move callback is called, and it 
-- increments the last angle the dial was rotated.
--
-- In all cases the value is incremented or decremented by Pi/10 (18 degrees).
--
-- If you press Shift while using the arrow keys the increment is reduced to 
-- Pi/100 (1.8 degrees). Press the Home key in the circular dial to reset to 0.
	
inherit
	IUP_CANVAS
		redefine
			set_expand,
			set_size,
			execute_button_press,
			execute_button_release,
			execute_mousemove_fnd,
			execute_valuechanged			
		end
	IUP_WIDGET_FGCOLOR
		redefine
			set_rgb_foreground_color
		end
	IUP_WIDGET_FLAT

create {ANY}
	dial_horizontal,
	dial_vertical,
	dial_circular

feature {ANY}

	dial_horizontal
		local
			type: STRING
			a_dial: POINTER
		do
			type := "HORIZONTAL"
			a_dial := int_dial(type.to_external)
			
			set_widget(a_dial)
		end

	dial_vertical
		local
			type: STRING
			a_dial: POINTER
		do
			type := "VERTICAL"
			a_dial := int_dial(type.to_external)
			
			set_widget(a_dial)
		end

	dial_circular
		local
			type: STRING
			a_dial: POINTER
		do
			type := "CIRCULAR"
			a_dial := int_dial(type.to_external)
			
			set_widget(a_dial)
		end

	-- Attributes

	set_density (value: REAL)
		-- number of lines per pixel in the handle of the dial. Default is 
		-- "0.2".
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "DENSITY", value.to_string)
		end

	set_expand (type: STRING)
		-- The default value is "False".
		do
			Precursor (type)
		end

	set_rgb_foreground_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- Foreground color. The default value is "64 64 64".
		do
			Precursor (red, green, blue)
		end

	set_size (width: INTEGER; height: INTEGER)
		-- The initial size is "16x80", "80x16" or "40x35" according to the dial 
		-- orientation.	
		do
			Precursor (width, height)
		end

	set_automatic_layout
		-- Set to allow the automatic layout use smaller values.
		do
			iup_open.set_attribute_null(Current, "SIZE")
		end

	set_unit_degrees
		do
			iup_open.set_attribute(Current, "UNIT", "DEGREES")
		end

	set_unit_radians
		-- This is the default value.
		do
			iup_open.set_attribute(Current, "UNIT", "RADIANS")
		end

	set_value (value: REAL)
		-- The dial angular value in radians always. The value is reset to zero 
		-- when the interaction is started, except for circular orientation. When 
		-- orientation is vertical or horizontal, the dial measures relative 
		-- angles. When orientation is circular the dial measure absolute angles, 
		-- where the origin is at 3 O'clock.
		do
			iup_open.set_attribute(Current, "VALUE", value.to_string)
		end

	get_value: REAL
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "VALUE")

			if str.is_real then
				Result := str.to_real
			end
		end

	-- Callbacks

	set_cb_button_press (act: FUNCTION[TUPLE[IUP_DIAL, REAL_64], STRING])
		-- Called when the user presses the left mouse button over the dial. The 
		-- angle here is always zero, except for the circular dial.
		--
		-- ih: identifier of the element that activated the event.
		-- angle: the dial value converted according to UNIT.
		local
			operation: INTEGER
		do
			cb_button_press := act

			if cb_button_press /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BUTTON_PRESS_CB", "NONEEDED", operation)
		end

	set_cb_button_release (act: FUNCTION[TUPLE[IUP_DIAL, REAL_64], STRING])
		-- Called when the user releases the left mouse button after pressing it 
		-- over the dial.
		--
		-- ih: identifier of the element that activated the event.
		-- angle: the dial value converted according to UNIT.
		local
			operation: INTEGER
		do
			cb_button_release := act

			if cb_button_release /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BUTTON_RELEASE_CB", "NONEEDED", operation)
		end

	set_cb_mouse_move (act: FUNCTION[TUPLE[IUP_DIAL, REAL_64], STRING])
		-- Called each time the user moves the dial with the mouse button 
		-- pressed. The angle the dial rotated since it was initialized is passed 
		-- as a parameter.
		--
		-- ih: identifier of the element that activated the event.
		-- angle: the dial value converted according to UNIT.
		local
			operation: INTEGER
		do
			cb_mousemove := act

			if cb_mousemove /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MOUSEMOVE_CB", "Fnd", operation)
		end

	set_cb_value_changed (act: FUNCTION[TUPLE[IUP_DIAL], STRING])
		-- Called after the value was interactively changed by the user. It is 
		-- called whenever a BUTTON_PRESS_CB, a BUTTON_RELEASE_CB or a 
		-- MOUSEMOVE_CB would also be called, but if defined those callbacks will 
		-- not be called.
		local
			operation: INTEGER
		do
			cb_valuechanged := act

			if cb_valuechanged /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "VALUECHANGED_CB", "NONEEDED", operation)
		end

feature {IUP}

	execute_button_press (angle: REAL_64): STRING
		do
			Result := cb_button_press.item([Current, angle])
		end

	execute_button_release (angle: REAL_64): STRING
		do
			Result := cb_button_release.item([Current, angle])
		end

	execute_mousemove_fnd (angle: REAL_64): STRING
		do
			Result := cb_mousemove.item([Current, angle])
		end

	execute_valuechanged: STRING
		do
			Result := cb_valuechanged.item([Current])
		end

feature {}

	-- Callbacks

	cb_button_press: FUNCTION[TUPLE[IUP_DIAL, REAL_64], STRING]
	cb_button_release: FUNCTION[TUPLE[IUP_DIAL, REAL_64], STRING]
	cb_mousemove: FUNCTION[TUPLE[IUP_DIAL, REAL_64], STRING]
	cb_valuechanged: FUNCTION[TUPLE[IUP_DIAL], STRING]

	-- Internals
	
	int_dial (type: POINTER): POINTER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "IupDial"
         }"
      end

end -- class IUP_DIAL

-- The MIT License (MIT)

-- Copyright (c) 2019 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
